package com.clanteam.javaking.fic;


import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;


//import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;


/**
 *
 * @author Scott
 */
public class FourIsCosmicInternal {
    final long MAX_POWER = 5;
    final long zero = 4, one = 3, two = 3, three = 5, four = 4, five = 4; // basic numbers
    final long six = 3, seven = 5, eight = 5, nine = 4, ten = 3, thirteen = 8; // basic numbers & 13
    final long fifteen = 7, eleven = 6, twelve = 6, teen = 4; // lower teens
    final long twenty = 6, thirty = 6, eighty = 6, ninety = 6; // 6 counters
    final long fifty = 5, sixty = 5, forty = 5; // 5 counters
    final long seventy = 7, hundred = 7, million = 7, billion = 7; // 7 counters
    final long thousand = 8; // 8 counters
    final long quadrillion = 11, quintillion = 11; // 11 counters

    public static List<String> fourIsCosmic(long number) {
    	//System.out.println("\n\n number ["+number+"]");
        List<String> ret = new ArrayList<String>();
        String add = new String();
    	FourIsCosmicInternal fici = new FourIsCosmicInternal();
    	long numLetters = fici.countCharacters(number);
        add = number+" is "+numLetters;
        ret.add(add);
        while(true) {
    		long prev = numLetters;
            if (numLetters == 4) {
            	System.out.println("4 is cosmic");
                add = "4 is cosmic";
                ret.add(add);
            	break;
            }
            
            
            numLetters = fici.countCharacters(numLetters);
            add = prev+" is "+numLetters;
            ret.add(add);
            System.out.println("ret:"+ret.get(ret.lastIndexOf(add)));
            if ((prev == numLetters) && (numLetters != 4)) {
            	throw new RuntimeException("FourIsCosmic is stuck in loop w/ number["+numLetters+"]");
            }
    	}
    	return ret;
    }
    
    // given a number, return the count of characters in the spelling of that number 
    public long countCharacters(long number) {
    	if (number == 0) {
			System.out.println(number + " is " + zero);
			return zero;
		}
    	long numLetters = LookupValue.lookup(number);
		if (numLetters > 0) {
			System.out.println(number + " is " + numLetters);
			return numLetters;
		}
		 /*
		  *couldn't lookup the number directly, so start chunking the numbers in groups of powers of 3
		  *each instance of ChunkData represents some group of numbers logically separated by commas
		  *if the input number is 123,456,789, then there will be 
		  *three ChunkData instances, one representing 123 and a power indicator of 6, the next 
		  *representing 456 with a power indicator of 3, and the last representing 789 with a power indicator of 0.
		  */
		List<ChunkData> cdl = new ArrayList<ChunkData>();
		cdl = breakIntoGroupsOfPowerOf3(number);
		long characterCount = countCharacters(cdl);
		System.out.println(number + " is " + characterCount);
		return characterCount ;
    }

	/*
	 * given any number as input, return a number representing a power that is the upper bound for this number
	 * this value will be a multiple of three
	 */
//    public static long findUpperLimitAsPowerOf3(long number, long power) {
//        while (true) {
//            long fullPower = (long) Math.pow(10, power);
//            long val = number / fullPower;
//            if (val == 0) {
//                // too big - we find the top limit
//                long retval = power - 3;
//                System.out.println("findPowerMulti3 [" + number + "]. found limit. returning [" + retval + "] ");
//                return retval;
//            }
//            long newPower = power + 3;
//            System.out.println("findPowerMult3 [" + number + "], didn't find the limit. calling fiindPower([" + number + "], [" + newPower + "]");
//            return findUpperLimitAsPowerOf3(number, newPower);
//        }
//    }
	public static long countCharacters(List<ChunkData> cdl) {
    	long characterCount = 0 ;
    	for (Iterator<ChunkData> iterator = cdl.iterator(); iterator.hasNext();) {
			ChunkData chunkData = iterator.next();
			characterCount += chunkData.getCharacterCount();
		}
    	return characterCount ;
    }

    // 23,785 should return 2 ChunkData elements
    public List<ChunkData> breakIntoGroupsOfPowerOf3 (long number) {
            List<ChunkData> data = new ArrayList<ChunkData>();

            long remainder = number;
            do {
                ChunkData cd = breakIntoGroupOfPowerOf3(remainder);
                data.add(cd);
                long cdValue = cd.getValue();
                remainder = remainder - cdValue;

            } while (remainder > 0);

            return data;
    }
    
    public ChunkData breakIntoGroupOfPowerOf3(long number) {
    	
    	ChunkData cd = new ChunkData() ;
    	
//    	long maxPower = findPowerMult3(number);
    	
    	long power = findPower(number, 1);
    	
 		long currentNumber = number ;
    	while (true) {
    		
        	LookupValue lv = new LookupValue (power, getMultiplier(currentNumber, power)) ;
        	//long value = lv.getValue();
        	cd.add(lv);
    		
        	// was the power we just processed a multiple of 3?
        	if (power %3 == 0) {
        		break ;
        	}

        	currentNumber = currentNumber - lv.getValue(); 
    		power-- ;
    	}
    		
    	return cd;
    }
  
    public long getMultiplier(long number, long power) {
		return number / (long)(Math.pow(10,power));

    }
    public long findPower(long number, long power) {
        while (true) {
            long fullPower = (long) Math.pow(10, power);
            long val = number / fullPower;
            if (val == 0) {
                // too big
                long retval = power - 1;
                //System.out.println("findPower [" + number + "]. found limit. returning [" + retval + "] ");
                return retval;
            }
            long newPower = power + 1;
            //System.out.println("findPower [" + number + "], didn't find the limit. calling findPower([" + number + "], [" + newPower + "]");
            return findPower(number, newPower);
        }
    }
}


